Docker(三)构建镜像以及在单一容器运行

容器基本操作

启动容器:

1
docker run IMAGE [COMMAND] [ARGS...]

run 命令解释:

  • 1.命令会检测当前要运行的镜像在本地存不存在,若不存在他会自动 pull 下来再运行
  • 2.运行后会启动一个容器, 并且开启一个文件系统, 你可以直接在容器内创建文件夹. 运行一个指定的程序, 当程序退出后, 容器也就退出了
  • 3.运行时的容器无法删除, 只能停止后删除, 或者加上 -f 参数强制删除

示例: docker run centos echo ‘hello docker’

启动守护式容器:

1
docker run -i -t IMAGE /bin/bash
-i --interactive=true|false 默认是false:允许你对容器内的标准输入 (STDIN) 进行交互  
-t --tty=true|false 默认是false:在新容器内指定一个伪终端或终端  
示例: docker run -i -t centos /bin/bash  
使用exit退出守护式容器.

查看容器:

docker ps [-a] [-l]
    -a:表示列举所有的容器
    -l :表示列举最近创建的容器.    
默认情况容器在运行之后就停止了,ps只是显示正在运行的容器.

查看容器详细信息:

docker inspect [容器名字|容器唯一标识]
要查看容器详细信息,需要输入很长串的字母.
docker允许用户自定义容器的名字:
    docker run --name=自定义名 -i -t IMAGE /bin/bash

重新启动停止的容器:

docker start [-i] 容器名

删除停止的容器:

docker rm 容器名    
只能删除停止的容器,但是不能删除正在运行中的容器.

守护式容器

以守护形式运行容器:

启动容器:docker run -i -t IMAGE /bin/bash
退出但不关闭容器:Ctrl+P Ctrl+Q

附加到运行中的容器:

docker attach 容器名

启动守护式容器:

docker run -d 镜像名 [COMMAND] [ARG...]
示例:docker run --name dc1 -d centos /bin/sh -c "while true; do echo helloworld;sleep 1;done"

查看容器日志:

docker logs [-f] [-t] [--tail] 容器名
    -f --follow=true|false 默认为false 一致跟踪日志的变化,并返回结果
    -t --timestamps=true|false 默认为false 在返回的结果上加上时间戳
    --tail = “all” 返回后几行的日志数据.

查看容器内进程:

docker top 容器名

在运行中的容器内启动新进程:

docker exec [-d] [-i] [-t] 容器名 [COMMAND] [ARG...]
示例:docker exec -i -t dc1 /bin/bash

停止守护式容器:

docker stop 容器名 :发送一个信号给容器,等待容器的关闭.
docker kill 容器名 :直接停止容器.

设置容器的端口映射

run [-P] [-p]
    -P , --publish-all=true|false 默认为false :将为容器所有暴露的端口进行映射.
        示例:docker run -P -i -t centos /bin/bash
    -p, --publish=[] :给指定的端口进行映射.
        方式一:containerPort
            示例:docker run -p 80 -i -t centos /bin/bash
        方式二:hostPort:containerPort
            示例:docker run -p 8080:80 -i -t centos /bin/bash
        方式三:ip::containerPort
            示例:docker run -p 0.0.0.0:80 -i -t centos /bin/bash
        方式四:ip:hostPort:containerPort
            示例:docker run -p 0.0.0.0:8080:80 -i -t centos /bin/bash

Docker镜像和仓库

列出镜像

docker images [OPTIONS] [REPOSITORY]
    -a, --all=false :表示列举出所有的镜像.默认并不显示中间层的镜像.
    -f, --filter=[] :表示添加过滤条件.
    --no-trunc=false:表示对信息进行截断.默认情况是会截断镜像的唯一id的.
    -q, --quiet=false:表示值显示镜像的唯一id

REPOSITORY 仓库: 是一切镜像的集合.
REGISTRY 注册仓库:包含REPOSITORY 的仓库.
TAG 标签:我们之前运行的centos默认使用的是lastest的标签.仓库名+镜像名就能唯一确定一个镜像.
如果使用docker images -a 看到没有仓库名和标签名的其实是中间层镜像.

删除镜像

docker rmi [OPTIONS] IMAGE [IMAGE...]
-f, --force=false :表示强制删除镜像.
--no-proune=false :会保留未被打标签的父镜像.
删除对应仓库所有的镜像:docker rmi  $(docker images -q centos)

获取和推送镜像

Docker中REGISTER仓库有些类似Maven的中央仓库.我们通过类似Git中的pull和push命令从REGISTER仓库中拉取镜像和推送镜像.

查找镜像:

方式一:
        Docker Hub    https://hub.docker.com/
方式二:
        docker search [OPTIONS] TERM
            --no-trunc=false : 截断操作
            -s,--starts=0 : 每个镜像都会有star,我们可以通过-s操作来限定star数.
             一次最多返回25条记录.

拉取镜像:

docker pull [OPTIONS] NAME [:TAG]
-a, --all-tags=false :会把所有仓库中标记的镜像下载到本地中
示例:docker pull ubuntu:14.04
我们会发现我们拉取镜像的速度非常慢.我们可以修改REGISTER仓库的地址来加快下载的速度.    
https://www.daocloud.io/mirror#accelerator-doc
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://a7775d97.m.daocloud.io
sudo systemctl restart docker
docker pull ubuntu:12.10
我们会发现明显速度已经提升很多了.

推送镜像:

docker push 镜像名.
步骤:
    1.注册hub的账号.
    2.登陆hub的账号.docker login
    3.使用push命令推送到hub中
        docker push username/repo name/tag

构建镜像

构建镜像可以让我们保存对容器的修改,并再次使用.提供了自定义镜像的能力,以软件的形式打包并方法服务及其运行环境.
docker里面提供了两种方式来构建镜像:

        方式一:docker commit 通过容器构建
        方式二:docker build 通过Dockerfile文件构建.

使用commit构建镜像:

docker commit [OPTIONS] CONTAINER(容器名称) [REPOSITORY[:TAG]]
    -a, --author=”” 指定镜像的作者.
    -m, --message=”” 提交信息,构建信息
    -p, --pause=true 默认情况在commit的时候会暂停容器,使用这个参数可以在构建的时候不暂停容器.
    步骤:
        1.创建一个容器并安装nginx服务
        docker run -it --name commit_test -p 80 centos /bin/bash
        2.在容器内部安装nginx,和之前步骤一样
        3.提交镜像.
        docker commit -a '作者信息' -m '备注' commit_test(容器名称) username/repo:tag
        4.通过docker images命令可以看到我们刚构建的镜像.
        5.推送到远程仓库 docker push username/repo:tag

使用Dockerfile定义容器:

Dockerfile定义容器内环境中发生的事情。对网络接口和磁盘驱动器等资源的访问在此环境中进行虚拟化,该环境与系统的其他部分隔离,因此您需要将端口映射到外部世界,并具体说明要“复制”到哪些文件。您可以预期在此Dockerfile中定义的应用程序的构建在其运行的任何位置都表现完全相同。

什么是Dockerfile文件呢?其实就是包含了一些执行命令的文本文件.

docker build [OPTIONS] PATH|URL|-
    --force-rm=false
    --no-cache=false
    --pull=false
    -q, --quiet=false
    -rm=true
    -t, --tag=””

步骤:
    1.在宿主机中,我们创建存放Dockerfile文件的目录和Dockerfile文件.
        mkdir -p dockerfile/df_test1
        cd dockerfile/df_test1/
        vi Dockerfile
    2.编写Dockfile文件
        # First docker file for test
        FROM centos
        MAINTAINER lanxw0720 "lanxiongwei@wolfcode.cn"
        RUN yum install -y wget
        RUN wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
        RUN yum install -y epel-release
        RUN yum install -y nginx
        EXPOSE 80
    3.使用build命令构建镜像.
        docker build -t='lanxw0720/df_test1' .
    4.通过我们构建好的镜像来创建容器.
        docker run -d --name nginx_web3 -p 80 lanxw0720/df_test1 /usr/sbin/nginx -g "daemon off;"

Dockerfile的指令格式

指令主要分为两种:
    注释 : # Comment
    指令 : INSTRUCTION argument
FROM:
    包含两种格式:
    1. FROM  <image>
    2. FROM  <image>:<tag>
    image要求是已经存在的镜像,我们也称为基础镜像.必须是第一条非注释指令

MAINTAINER:
    指定镜像的作者信息,包含镜像的所有者和联系信息.
RUN:
    指定当前镜像中运行的命令
    RUN  <command> (shell模式)
            /bin/sh -c command
            RUN echo hello

    RUN [“executable”,”param1”,”param2”] (exec模式)
    RUN [“/bin/bash”,”-c”,”echo hello”]
    每个RUN命令都会在当前镜像的上层创建一个新的镜像来运行指令.
    
EXPOSE:
    指定运行该镜像的容器使用的端口.
    虽然我们在构建镜像的时候暴露了端口号,但是我们在运行容器的时候依然需要指定端口的映射.
    我们使用EXPOSE只是告诉Docker运行该镜像的容器会使用80端口,出于安全的考虑,docker并不会打开该端口.
    而是需要我们在使用该镜像运行容器的时候指定端口的映射.

CMD:
    CMD指令提供容器默认运行的命令,和之前讲的RUN指令类似.都是执行一个命令,但是RUN命令指定的命令是在镜像构建的过程运行的.
    CMD的命令是在容器运行的时候运行的.如果我们在docker run命令中指定运行的命令的时候,CMD的指令会被覆盖,默认命令就不会执行.
    CMD命令是指定容器启动的时候默认命令.
    两种模式.
    CMD [“executable”,”param1”,”param2”] (exec模式)
    CMD command param1 param2 (shell 模式)
    CMD [”param1”,”param2”] (作为ENTRYPOINT指令的默认参数.)

    通过构建的镜像来创建容器
    docker run -p 80 --name cmd_test1 -itd lanxw0720/df_test3
    docker top cmd_test1
    发现已经启动nginx了.
    如果我们在启动的时候指定了参数,默认的CMD命令就会被覆盖了.
    
    
ENTRYPOINT:
    这个和我们刚刚讲的CMD指令非常相似,唯一的区别:不会给docker run的启动命令给覆盖.
    如果需要覆盖ENTRYPOINT的指令,需要在docker run使用docker run --entrypoint覆盖.
    ENTRYPOINT [“executable”,”param1”,”param2”] (exec模式)
    ENTRYPOINT command param1 param2 (shell 模式)
    示例:
    docker build -t="lanxw0720/df_test4" .
    docker run -p 80 --name ep_test1 -d lanxw0720/df_test4 
    docker ps -l
    可以发现,启动的容器依然使用的ENTRYPOINT指定的命令执行.

ADD:
    将文件和目录复制到使用dockerfile构建的镜像中.
    目标的来源可以本地的地址也可以是远程地址.
    如果是本地地址,本地地址必须是构建目录中的相对地址
    对于远程URL,docker并不推荐使用,更建议使用的是curl或者wget的命令来获取
    目标路径需要指定镜像中的绝对路径
    ADD <src>...<dest>
    ADD [“<src>”...”<dest>”](适用于文件路径有空格的情况)

COPY:    
    同上.
    COPY<src>...<dest>
    COPY[“<src>”...”<dest>”](适用于文件路径有空格的情况)
    示例:
    在Dockerfile所在目录添加index.html文件
    docker build -t="lanxw0720/df_test6" .
    docker run -p 80 --name add_test1 -d lanxw0720/df_test6
    curl http://127.0.0.1:32775

VOLUME:
    用于基于镜像创建的容器添加卷,一个卷可以存在一个或者多个容器的特定目录.这个目录可以绕过联合文件系统.提供共享数据和持久化数据的功能.(后面单独讲)
WORKDIR:
    WORKDIR /path/to/workdir
    这个指令从指令创建一个容器是,在容器内部设置工作目录.ENTRYPOINT和CMD的命令都会在这个目录下执行.
    我们也可以使用这个命令给后续的构建中指定工作目录.
    通常会使用绝对路径,如果使用了相对路径,那这个路径会一致传递下去.如下所示:
    WORKDIR /a
    WORKDIR b
    WORKDIR c
    RUN pwd
    结果====>/a/b/c

ENV:
    ENV <key><value>
    ENV <key><value>...
    这个指令主要是来设置环境变量,这个环境变量在构建过程中和运行过程中都有效.

USER:
    USER daemon
    指定镜像会以什么样的用户去运行.
    比如:USER nginx
    基于该镜像启动的容器就会以nginx的用户来运行.
    如果没有指定USER,容器会使用root用户来运行.
    
ONBUILD:
    ONBUILD [INSTRUCTION]
    镜像触发器.
    当一个镜像被其他镜像作为基础镜像时执行
    会在构建过程中插入指令
    
    示例:
    docker run -p 80 --name onbuild_test1 -d lanxw0720/df_test7
    curl http://127.0.0.1:32776
    发现在构建这个镜像的时候并没有执行COPY命令.
    接下来我们基于这个镜像来构建新的镜像.
    
    docker build -t="lanxw0720/df_test8" .
    docker run -p 80 --name onbuild_test2 -d lanxw0720/df_test8
    curl http://127.0.0.1:32777
    此时发现已经执行COPY命令了.